home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-07 | 6.5 KB | 167 lines | [TEXT/MPS ] |
- XCMD and XFCN: The Magic Hooks That Extend HyperTalk
-
- (This documentation by Ted Kaehler, 14 July 87, HyperCard 1.0.1 and later)
-
- Dan Winkler has created an interface that allows powerful new commands
- to be added to HyperCard "in the field." When a command in a script
- cannot be found, HyperCard looks for a resource of type XCMD with
- the same name as the unknown command. Likewise, when a function cannot
- be found, HyperCard looks for a resource of type XFCN. Consider XCMDs
- and XFCNs to be extensions of stack scripts. Whenever a handler (for a
- command or function) is not found in a stack script, HyperCard
- immediately looks for a XCMD or XFCN in that stack. The total
- inheritance order is: Button (or Field), Card, Stack, stack XCMD, Home,
- home XCMD, HyperCard. An XCMD or XFCN is a code resource with no
- header bytes (just like a desk accessory). You can move them from
- file to file with ResEdit, ResCopy or with any other resource moving tool.
-
- The only thing passed into an XCMD or XFCN is a pointer to a XCmdBlock.
- It looks like this:
-
- XCmdPtr = ^XCmdBlock;
- XCmdBlock =
- RECORD
- paramCount: INTEGER; { number of arguments }
- params: ARRAY[1..32] OF Handle; { the arguments }
- returnValue: Handle; { the result of this XCMD }
- passFlag: BOOLEAN; { pass the message on? }
-
- entryPoint: ProcPtr; { call back to HyperCard }
- request: INTEGER; { what you want }
- result: INTEGER; { the answer it gives }
- inArgs: ARRAY[1..16] OF LongInt; { args XCMD sends HyperCard }
- outArgs: ARRAY[1..16] OF LongInt; { args HyperCard sends back }
- END;
-
- You read the agruments (they are handles to zero terminated strings),
- do whatever the purpose of this XCMD is, and optionally store a
- result into returnValue. All data values going to and from HyperTalk are
- zero-terminated ASCII strings.
-
- Resources of type XCMD are commands, and resourcs of type XFCN are
- fuctions that return a value. If you store a result string into
- returnValue in a command, the user can get it by asking for "the result"
- (useful for explaining why there was an error). In a function, you are
- expected to store the answer into returnValue.
-
- If passFlag is false (the normal case), this XCMD or XFCN has handled the
- message and the script resumes execution. If passFlag is true, HyperCard
- searches the remaining inheritance chain for another handler or
- XCMD with the same name. This is just like the "pass" control structure
- in a script.
-
- The second part of the XCmdBlock record has to do with
- calling HyperCard back in the middle of your code to ask a question.
- If you wanted manage the call to HyperCard yourself, you would
- fill inArgs with your arguments, put a request code in request,
- and JSR to the address in entryPoint. HyperCard returns the values you
- requested in outArgs and a reslut code in result.
-
- However, Dan Winkler has packaged the entire range of calls on HyperCard,
- so that if you are using Pascal, you can simply call a procedure. The file
- XCmdGlue.inc has the glue procedures. Handle is always a handle to a
- zero-terminated sting. If a handle is returned, you are responsible for
- freeing it. <<is this true?>>
-
- FUNCTION EvalExpr(expr: Str255): Handle;
- Given a HyperTalk expression in ASCII, return a handle to a zero-terminated
- string with the answer.
-
- PROCEDURE SendCardMessage(msg: Str255);
- Send a HyperCard message (command) to the current card.
-
- FUNCTION GetGlobal(globName: Str255): Handle;
-
- PROCEDURE SetGlobal(globName: Str255; globValue: Handle);
-
- FUNCTION GetFieldByName(cardFieldFlag: BOOLEAN; fieldName: Str255): Handle;
-
- FUNCTION GetFieldByNum(cardFieldFlag: BOOLEAN; fieldNum: INTEGER): Handle;
-
- FUNCTION GetFieldByID(cardFieldFlag: BOOLEAN; fieldID: INTEGER): Handle;
-
- PROCEDURE SetFieldByName(cardFieldFlag: BOOLEAN; fieldName: Str255; fieldVal: Handle);
-
- PROCEDURE SetFieldByNum(cardFieldFlag: BOOLEAN; fieldNum: INTEGER; fieldVal: Handle);
-
- PROCEDURE SetFieldByID(cardFieldFlag: BOOLEAN; fieldID: INTEGER; fieldVal: Handle);
-
- PROCEDURE ZeroToPas(zeroStr: Ptr; VAR pasStr: Str255);
- Convert a zero terminated string to a Pascal string. You create the
- Pascal string and pass it in as a VAR parameter. Useful for converting
- the arguments of any XCMD to Pascal strings. (See PasToZero below).
-
- FUNCTION StrToNum(str: Str19): LongInt;
- Convert ASCII of a decimal number to the number.
-
- FUNCTION StrToLong(str: Str19): LongInt;
- Convert ASCII of a decimal number to the number. Negative numbers not
- accepted.
-
- FUNCTION StrToExt(str: Str31): Extended;
-
-
- FUNCTION StrToBool(str: Str31): BOOLEAN;
- Convert ASCII "true" and "false" to Pascal booleans.
-
- FUNCTION StringLength(strPtr: Ptr): LongInt;
-
- FUNCTION StringEqual(str1,str2: Str255): BOOLEAN;
-
- FUNCTION StringMatch(pattern: Str255; target: Ptr): Ptr;
-
- PROCEDURE ReturnToPas(zeroStr: Ptr; VAR pasStr: Str255);
-
- PROCEDURE ScanToReturn(VAR scanPtr: Ptr);
-
- PROCEDURE ScanToZero(VAR scanPtr: Ptr);
-
- PROCEDURE ZeroBytes(dstPtr: Ptr; longCount: LongInt);
-
- PROCEDURE CopyBytes(srcPtr,dstPtr: Ptr; byteCount: LongInt);
- Generally useful for moving data in memory.
-
- PROCEDURE DivMod(numerator: LongInt; denominator: INTEGER;
- VAR quotient: LongInt; VAR remainder: INTEGER);
- Division with remainder.
-
- FUNCTION LongToStr(posNum: LongInt): Str19;
- Convert a longInt to decimal ASCII.
-
- FUNCTION NumToStr(num: LongInt): Str19;
- Convert a longInt to decimal ASCII, using a minus sign for negative
- numbers.
-
- FUNCTION NumToHex(num: LongInt; nDigits: INTEGER): Str19;
- Convert a longInt to hexadecimal ASCII, using a minus sign for
- negative numbers.
-
- FUNCTION ExtToStr(num: Extended): Str31;
-
- FUNCTION BoolToStr(bool: BOOLEAN): Str31;
- Convert a boolean to ASCII "true" or "false".
-
- FUNCTION PasToZero(str: Str255): Handle;
- Convert a pascal string to a zero-terminated string. You'll need to do
- this for any result or argument you return to HyperTalk.
-
-
- Here are the files you will need:
-
- HyperXCmd.p
- XCmdGlue.inc
-
- Here are the typical MPW commands for compiling an XCMD
-
- pascal -w SendSerial.p
- link -m ENTRYPOINT -o HyperCommands -rt XCMD=222 -sn Main=SendSerial ∂
- SendSerial.p.o "{MPW}"Libraries:interface.o
-
- If you don't use any of the routines in interface.o, its just
-
- pascal Flash.p
- link -o HyperCommands -rt XCMD=0 -sn Main=Flash Flash.p.o
-
- After executing these, use ResEdit or ResCopy (a resource mover in a HyperCard
- stack, like the Font/DA Mover) to move the XCMD or XFCN from HyperCommands
- to the proper stack.